﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ly_thuyet_toi_uu
{
    class clsNelderMead
    {
        struct stPoint
        {
            public int x;
            public int y;
        }

        int f(int x1, int x2)
        {
            return -x1 * x2;
        }


     public   int Run()
        {
            stPoint X1, X2, X3;
            stPoint C; // Dinh trong tam 
            stPoint Xr; //
            stPoint Xm = new stPoint(); // Huong
            stPoint Xn = new stPoint();
            stPoint Xc = new stPoint(); // To do co
            int fp, fg, fq = 0;
            int fr, fm, fc = 0;

            double alpha = 1.0;
            // Buoc 1- Chon cac dinh
            X1.x = -2; X1.y = 3; //fq
            X2.x = -1; X2.y = 7; //fp
            X3.x = -2; X3.y = 7; //fg

            // Buoc 2 - Tinh cac gia tri fp-max,fp<fg<fq,fq-min
        Buoc2:
            fq = f(X1.x, X1.y);
            Console.WriteLine("fq({0},{1}) = {2}", X1.x, X1.y, fq);
            fp = f(X2.x, X2.y);
            Console.WriteLine("fp({0},{1}) = {2}", X2.x, X2.y, fp);
            fg = f(X3.x, X3.y);
            Console.WriteLine("fg({0},{1}) = {2}", X3.x, X3.y, fg);

            // Buoc 3 - Xac dinh trong tam
            C.x = (X1.x + X3.x) / 2;
            C.y = (X1.y + X3.y) / 2;
            Console.WriteLine("Toa Do Tam C({0},{1})", C.x, C.y);
            // Tinh toa do Xr de xac dinh huong
            Xr.x = C.x + 1 * (C.x - X2.x);
            Xr.y = C.y + 1 * (C.y - X2.y);
            fr = f(Xr.x, Xr.y);
            Console.WriteLine("fr({0},{1}) = {2}", Xr.x, Xr.y, fr);
            // Buoc 5 - S0 sanh fr va fq
            //1. Neu fr < fq thi gia tri nho nhat, huong tu f0 den fr la tot nhat
            // Huong Xm la huong tot keo dan tu Xc, Xr
            if (fr < fq)
            {
                Xm.x = C.x + 2 * (Xr.x - C.x);
                Xm.y = C.y + 2 * (Xr.y - C.y);
                fm = f(Xm.x, Xm.y);
                Console.WriteLine("fm({0},{1}) = {2}", Xm.x, Xm.y, fm);
                // Neu fm<fq thay Xp boi Xm roi kiem tra diem thu n+1
                // Neu hoi tu thi dung. Neu ko quay lai Buoc 3
                if (fm < fq)
                {
                    X1.x = Xm.x;
                    X1.y = Xm.y;
                    fq = f(X1.x, X1.y);
                    Console.WriteLine("fq({0},{1}) = {2}", X1.x, X1.y, fq);
                    // X[n+1] tiep huong tu x
                    Xm.x = C.x + 3 * (X1.x - C.x);
                    Xm.y = C.y + 3 * (X1.y - C.y);
                    fm = f(Xm.x, Xm.y);
                    Console.WriteLine("fm({0},{1}) = {2}", Xm.x, Xm.y, fm);
                    if (fq > fm) goto Buoc2;
                    if (fr > fq) // Mo Xm thay Xp boi m. Kiem tra tinh hoi tu. Neu ko quay lai Buoc 2
                    {
                        X3.x = Xm.x;
                        X3.y = Xm.y;
                        fp = f(X3.x, X3.y);
                        Xm.x = C.x + 3 * (X1.x - C.x);
                        Xm.y = C.y + 3 * (X1.y - C.y);
                        fm = f(Xm.x, Xm.y);
                        Console.WriteLine("fm({0},{1}) = {2}", Xm.x, Xm.y, fm);
                        if (fq > fm) goto Buoc2;
                    }
                }
            }
            // 2. Neu fr>fq và fr>fg. Thay p bang r, kiem tra neu chua hoi tu thi quay lai Buoc 2
            if ((fr > fq) & (fr > fg))
            {
                // Thay p=r;
                X2.x = Xr.x;
                X2.y = Xr.y;
                fp = f(X2.x, X2.y);
                Xm.x = C.x + 1 * (X2.x - C.x);
                Xm.y = C.y + 1 * (X2.y - C.y);
                fm = f(Xm.x, Xm.y);
                Console.WriteLine("fm({0},{1}) = {2}", Xm.x, Xm.y, fm);
                if (fq > fm) goto Buoc2;
            }
            //3. Neu fr > fq và fr>fg thi chuyen sang Buoc 6
            if ((fr > fq) & (fr > fg))
            {
                // Buoc 6
                // Neu fr< fp thay Xp boi Xr và fp=fr
                if (fr < fp)
                {
                    X2.x = Xr.x;
                    X2.y = Xr.y;
                    fp = fr;
                    Xc.x = C.x + (Xr.x - C.x) / 2;
                    Xc.y = C.y + (Xr.y - C.y) / 2;
                    fc = f(Xc.x, Xc.y);
                }
                else
                {
                    // Thuc hien phep co
                    Xc.x = C.x + (X2.x - C.x) / 2;
                    Xc.y = C.y + (X2.y - C.y) / 2;
                    fc = f(Xc.x, Xc.y);
                }

            }
            // Buoc 7 - So sanh fc va fp
            if (fc < fp)
            {
                // Thay fp bang fc
                X2.x = Xc.x;
                X2.y = Xc.y;
                fp = fc;
                goto Buoc2;
            }
            else // Chuyen qua buoc 8
            {
                // Lay X1 (Xq) lam chuan
                X2.x = (X2.x - X1.x) / 2;
                X2.y = (X2.y - X1.y) / 2;
                fp = f(X2.x, X2.y);

                X3.x = (X3.x - X1.x) / 2;
                X3.y = (X3.y - X1.y) / 2;
                fg = f(X3.x, X3.y);

                Xm.x = (Xm.x - X1.x) / 2;
                Xm.y = (Xm.y - X1.y) / 2;
                fm = f(Xm.x, Xm.y);

                if (fm < fp) goto Buoc2;

            }
            // Buoc 9 - Tinh deta2=Sum(f1)/(n+1);
            int deta2 = (fp + fq + fg + fm) / 4;
            // Neu deta2 < e nao do thi no rat gan voi fp
            Console.WriteLine("Diem dat gia tri min la: ({0},{1}) = {2}", X1.x, X1.y, fq);
            Console.ReadLine();
            return 0;
        }
    }
}
